<template>
  <div class="employees-container">
    <div class="app-container">
      <!-- 通用工具栏组件使用 -->
      <page-tools>
        <!-- 自定义左侧内容 -->
        <template #slot-left>
          <span>共19条记录</span>
        </template>

        <!-- 自定义右侧内容 -->
        <template #slot-right>
          <el-button type="danger" size="small" @click="uploadExcelClickFn">导入excel</el-button>
          <el-button type="success" size="small" @click="exportExcelClickFn">导出excel</el-button>
          <el-button type="primary" size="small" @click="addEmpClickFn">新增员工</el-button>
        </template>
      </page-tools>

      <el-card style="margin-top: 10px;">
        <el-table border :data="employeesList" :default-sort="{prop: 'timeOfEntry', order: 'descending'}">
          <el-table-column label="序号" type="index" />
          <el-table-column label="姓名" prop="username" />
          <el-table-column label="头像" prop="staffPhoto" />
          <el-table-column label="手机号" prop="mobile" />
          <el-table-column label="工号" prop="workNumber" />
          <el-table-column sortable label="聘用形式" prop="formOfEmployment" :formatter="formOfEmploymentFormatterFn" />
          <el-table-column label="部门" prop="departmentName" />
          <el-table-column sortable label="入职时间" prop="timeOfEntry" :sort-method="timeOfEntrySortFn">
            <template v-slot="scope">
              {{ scope.row.timeOfEntry | formatTime }}
            </template>
          </el-table-column>

          <el-table-column label="操作" width="280">
            <template v-slot="scope">
              <el-button type="text" size="small" @click="lookDetailFn(scope.row.id)">查看</el-button>
              <el-button type="text" size="small">分配角色</el-button>
              <el-button type="text" size="small" @click="delEmpFn(scope.row.id)">删除</el-button>
            </template>
          </el-table-column>
        </el-table>

        <!-- 分页组件 -->
        <el-row type="flex" justify="center" align="middle" style="height: 60px">
          <!-- 分页区域 -->
          <el-pagination
            :current-page="query.page"
            :page-sizes="[10, 15, 20, 25]"
            :page-size="query.size"
            layout="total, sizes, prev, pager, next, jumper"
            :total="total"
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
          />
        </el-row>
      </el-card>
      <!-- 新增员工-弹窗 -->
      <el-dialog
        title="新增员工"
        :visible.sync="showDialog"
        @close="closeDialogFn"
      >
        <emp-dialog
          ref="empDialog"
          :show-dialog.sync="showDialog"
          :departments-tree-list="departmentsTreeList"
          @addEmpEV="addEmpFn"
        />
      </el-dialog>
    </div>
  </div>
</template>

<script>
import { getEmployeesListAPI, delEmployeesAPI, addEmployeesAPI } from '@/api/employees'
import { getDepartmentsListAPI } from '@/api/departments'
import { tranListToTreeData } from '@/utils'
import EmployeeEnum from '@/api/constant'
import empDialog from './empDialog.vue' // el-form表单组件封装在内
import dayjs from 'dayjs'
// import * as excel from '@/vendor/Export2Excel'
// console.log(excel)
export default {
  name: 'Employees',
  components: {
    empDialog
  },
  filters: {
    formatTime(time) {
      return dayjs(time).format('YYYY-MM-DD')
    }
  },
  data() {
    return {
      query: {
        page: 1, // 页码
        size: 10 // 每页条数
      },
      employeesList: [], // 员工列表
      total: 0, // 数据总条数
      showDialog: false, // 新增员工-弹窗是否出现
      departmentsTreeList: [] // 部门列表(树形数据)
    }
  },
  created() {
    this.getEmployeesListFn()
    // const list = [1, 5, 3, 7, 0, 2, 4]
    // const result = list.sort((a, b) => a - b)
    // console.log(result)
    this.getDepartmentsListAPI()
  },
  methods: {
    // 获取员工列表
    async getEmployeesListFn() {
      const res = await getEmployeesListAPI(this.query)
      console.log(res)
      this.employeesList = res.data.rows
      this.total = res.data.total
    },
    // 获取部门列表
    async getDepartmentsListAPI() {
      const res = await getDepartmentsListAPI()
      console.log(res)
      this.departmentsTreeList = tranListToTreeData(res.data.depts, '')
    },
    // 每页显示的条数发生改变时触发
    handleSizeChange(newSize) {
      this.query.size = newSize
      this.getEmployeesListFn()
    },

    // 当前页面发生改变时触发
    handleCurrentChange(newPage) {
      this.query.page = newPage
      this.getEmployeesListFn()
      // 扩展知识: 我直接把请求放在created里, 以后this.created()行不行? 不行
      // 因为钩子函数(生命周期函数8个), 是没有挂载到组件的身上, 所以不能用this调用钩子函数
    },
    // 格式化->聘用形式列内容
    formOfEmploymentFormatterFn(row) {
      // row: 其实就是scope.row->行的数据对象
      const obj = EmployeeEnum.hireType.find(item => item.id === row.formOfEmployment * 1)
      // 找到了用value的值, 找不到就返回'未知'字符串给列内容
      return obj ? obj.value : '未知'
    },
    // 入职时间->排序
    timeOfEntrySortFn(a, b) {
      // 还要和数组的sort的表现一致, 必须return一个数字 (小于0, a在前, b在后, 等于0不动, 大于0, b在前, a在后)
      // a和b是对象不能直接-, 但是取出来了日期字符串(因为中间有-), 所以这个日期字符串也不能做减法(硬减直接是NaN)
      // return NaN相当于return 了0, 所有顺序压根没动
      // 还有可能是前端直接把日期对象硬转成了字符串"2022-01-31T16:00:00.000Z"
      // 所以不用思考字符串之间的比较了
      // 解决: 试着转成日期对象, 算毫秒进行对比
      // new Date() 有要求, 传入的年月日, 是年/月/日的字符串, 是年-月-日字符串也可以
      // 但是数据不一致性, undefined我们就给它弄个1970-01-01日(算最小的)
      if (!a.timeOfEntry) {
        a.timeOfEntry = '1970-01-01'
      }
      if (!b.timeOfEntry) {
        b.timeOfEntry = '1970-01-01'
      }
      const aDate = new Date(a.timeOfEntry)
      const bDate = new Date(b.timeOfEntry)

      return aDate.getTime() - bDate.getTime()
      // 如果不指定排序规则, 在内部排序时候, 先看看你有没有自定义的方法有就用, 没有内部就用sort方法排序, 如果内部发现排不出来, 就尝试用索引值来排序
    },
    // 删除-员工-点击事件
    async delEmpFn(id) {
      await delEmployeesAPI(id)
      if (this.employeesList.length === 1) {
        this.query.page--
        if (this.query.page <= 0) {
          this.query.page = 1
        }
      }
      this.getEmployeesListFn()
    },
    // 新增员工-按钮-点击事件(头部工具栏右上角按钮)
    addEmpClickFn() {
      this.showDialog = true
    },
    // 新增员工->表单确定事件
    async addEmpFn(formObj) {
      // addEmployeesAPI() -> 返回在原地的是一个axios函数调用后在原地的一个Promise对象
      // Promise对象内包裹着一个ajax异步任务请求
      // ajax异步成功->Promise对象改为成功状态(把要执行then()里函数体代码/await这样, 推到微任务队列里, JS执行栈就执行await这一行代码了)

      // Promise对象可以.then()拿到成功(Promise内resolve()的结果
      // 也可以使用await取代.then(), 直接把后台返回的成功的结果留在原地

      // await不能"直接"拿到失败的结果
      // 解决: try+catch捕获 / .catch(err => err): 链式调用特性
      // try {} catch(err) {}

      // 因为date-picker绑定的是日期对象, 但是传入给axios会全都试着转成JSON字符串, 所以格式就不太对, 所以需要我们自己提前在前端把日期对象转成年-月-日的日期格式字符串
      // 自己写: 思路, 拿到日期对象的年数字, 月数字, 日数字, 前面补0拼接字符串
      // 借助包: dayjs (专门处理时间的各种方法)

      const result = dayjs(formObj.timeOfEntry).format('YYYY-MM-DD')
      formObj.timeOfEntry = result
      const res = await addEmployeesAPI(formObj)
      console.log(res)
    },
    // 弹层+表单关闭事件
    closeDialogFn() {
      // 表单重置
      // this.$refs.empDialog // empDialog组件对象(右侧this的值)
      // 右侧this.$refs.addForm // el-form组件对象
      this.$refs.empDialog.$refs.addForm.resetFields()
    },
    // 导入excel-按钮-点击事件
    uploadExcelClickFn() {
      this.$router.push('/excel')
    },
    async exportExcelClickFn() {
      // webpack提供的一个import函数
      // 引入一个文件, 原地得到一个Promise对象
      // Promise对象里成功的导入的结果, 就是文件模块导出的东西

      // 1. 拿到所有要导出的员工列表的数据->不能用上面的employeesList(它只有当前页条数数据)
      const res = await getEmployeesListAPI({
        page: 1,
        size: this.total // 总条数作为第一页, 一共要多少条
      }) // 不传参试试后台能不能把所有数据给我? 不能!因为后台默认返回10个
      // 2. 为何要自己写参数对象, 不用改this.query, 因为this.query是铺设页面用的, 而我此接口只为了导出所有的数据, 拿到所有数据
      console.log(res)
      const empList = res.data.rows // 员工数组列表

      // (不考虑顺序)笔记写法: 根据后台返回的字段直接全部导出10对key+value
      // 业务: 导出所有数据到表格文件里
      // 3. 准备数据结构, 为导出表格做准备 (数据处理)
      // 重点: 一定要知道现有的数据结构, 和想要的数据结构
      // 现有数组里套对象(英文key)
      // 想要二维数组, 小数组里装对象里关键值(表格一行数据)
      // 额外: 准备列表头数组(中文字符串数组)
      // 3.0 先准备列表头中文名字数组-映射好 英文对应中文转换值
      // const myObj = {
      //   'id': '编号',
      //   'password': '密码',
      //   'mobile': '手机号',
      //   'username': '姓名',
      //   'timeOfEntry': '入职日期',
      //   'formOfEmployment': '聘用形式',
      //   'correctionTime': '转正日期',
      //   'workNumber': '工号',
      //   'departmentName': '部门',
      //   'staffPhoto': '头像地址'
      // }
      // // 3.1 拿到英文key的字符串数组
      // const enKeyArr = Object.keys(empList[0]) // ['id', 'mobile', 'username', ...] 一共10个英文key字符串数组 -> 对象是无序的, 所以数组里值不一定哪个key在前还是在后面
      // // 3.2 遍历出每个英文key, 换出某个中文key, 形成数组
      // const zhKeyArr = enKeyArr.map(enKey => { // map会遍历左侧数组里每个值, 传给enKey形参执行一次函数体
      //   return myObj[enKey] // 执行一次函数体, 就return值给map内部, 收集到一个新数组里(push进)
      // }) // 等待map循环enKeyArr结束, 新的数组(里面中文key)返回在原地
      // // zhKeyArr 的值 ['编号', '手机号', '姓名]
      // console.log(zhKeyArr)

      // // 3.3 拿到值的数组
      // // Object.values(对象) // 对象所有的value值收集成一个数组返回在原地 ['604213123dsaf123', '13900002020', ...]
      // const valueArr = empList.map(obj => {
      //   return Object.values(obj) // 小数组, 值的数组 ['604213123dsaf123', '13900002020', ...]
      // }) // 遍历结束 [ [], [], [] ]

      // 考虑顺序 (页面上列保持一致顺序)
      // 4.0 准备一个列表头中文数组 (8个)
      const headerArr = ['序号', '姓名', '头像', '手机号', '工号', '聘用形式', '部门', '入职时间']
      // 4.1 数据key的映射关系(思路: 遍历上边数组里按照顺序, 取出中文的名字, 但是对应数组值的数组, 要从英文key对象中取出value值, 我要用中文key换到英文key然后去取到值)
      const myObj = {
        // 序号可以等遍历的时候直接用索引值, 而不是来自于英文对象里
        '姓名': 'username',
        '头像': 'staffPhoto',
        '手机号': 'mobile',
        '工号': 'workNumber',
        '聘用形式': 'formOfEmployment',
        '部门': 'departmentName',
        '入职时间': 'timeOfEntry'
      }
      // 4.2 按照顺序, 形成值的数组 (明确目标->想要数据结构->读代码(每个变量意思)读2-3遍->仿写3-5遍)
      const resultArr = empList.map((item, index) => {
        const valueArr = [] // 值小数组
        headerArr.forEach(zhKey => {
          if (zhKey === '序号') {
            valueArr.push(index + 1)
          } else {
            const enKey = myObj[zhKey]
            valueArr.push(item[enKey])
          }
        })
        return valueArr
      })
      console.log(resultArr)

      import('@/vendor/Export2Excel').then(excel => {
        excel.export_json_to_excel({ // 才是关键->调用Export2Excel.js中导出方法
          header: headerArr, // 表格列表头
          data: resultArr, // 二维数组(每个小数组代表一行数据)
          filename: '人资管理系统-员工列表', // 文件名
          autoWidth: true, // 自动宽度
          bookType: 'xlsx' // xlsx文件类型
        })
      })
    },
    // 点击查看->跳转员工详情页
    lookDetailFn(empId) {
      this.$router.push(`/employees/detail?id=${empId}`)
    }
  }
}
</script>

<style lang="scss" scoped></style>
